home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
WINSOUND
/
WAVSMALL.ZIP
/
WAVSMALL.TAR
/
WAVSMALL
/
sound
/
play.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-17
|
9KB
|
343 lines
/**************************************************************************************************/
/* WAV-File player/recorder - Version 0.1 */
/* using code of recplay.c from Audio Utilities for Linux 2.0 (c) Liam Corner */
/* (C) FF-Soft '93 */
/* Andre Fuechsel; email: af1@irz.inf.tu-dresden.de / fuechsel@freia.inf.tu-dresden.de */
/**************************************************************************************************/
#include <stdio.h>
#include <getopt.h>
#include <fcntl.h>
#include <linux/soundcard.h>
#define RECORD 0
#define PLAY 1
#define AUDIO "/dev/dsp"
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef struct { /* header for WAV-Files */
char main_chunk[4]; /* 'RIFF' */
DWORD length; /* length of file */
char chunk_type[4]; /* 'WAVE' */
char sub_chunk[4]; /* 'fmt' */
DWORD length_chunk; /* length sub_chunk, always 16 bytes */
WORD format; /* always 1 = PCM-Code */
WORD modus; /* 1 = Mono, 2 = Stereo */
DWORD sample_fq; /* Sample Freq */
DWORD byte_p_sec; /* Data per sec */
WORD byte_p_spl; /* bytes per sample, 1=8 bit, 2=16 bit (mono)
2=8 bit, 4=16 bit (stereo) */
WORD bit_p_spl; /* bits per sample, 8, 12, 16 */
char data_chunk[4]; /* 'data' */
DWORD data_length; /* length of data */
} wave_header;
int quiet_mode=0;
int time_limit=0;
int stereo = 0;
DWORD speed = 0, sample_size = 0;
int force_speed = 0, force_stereo = 0, force_sample_size = 0;
int mode, omode;
void err(char *err_str) /* future expansion planned */
{
fprintf(stderr, "%s \n", err_str);
}
int header_check(wave_header *head)
{
unsigned p;
int severity = 0;
p = head->length - head->data_length;
if ((p != 36) && (p != 37)) {
err("wrong length difference");
severity = 2;
}
if (strncmp(head->main_chunk, "RIFF", 4)) {
err("not in RIFF-Format");
severity = 2;
}
if (strncmp(head->chunk_type, "WAVE", 4)) {
err("not a WAVE-Type");
severity = 2;
}
if (strncmp(head->sub_chunk, "fmt ", 4)) {
err("not a WAVE-Format");
severity = 2;
}
if ((head->sample_fq * head->byte_p_spl) != head->byte_p_sec) {
err("wrong speed/freq.");
if (!severity) severity = 1;
}
if (severity == 2) return(0); else return(1);
}
void recplay(char *name)
{
int l, c, count;
int fd, fd1, audio;
int abuf_size;
DWORD length;
wave_header head;
char *audiobuf;
char tmp_name[] = "tmp.wav"; /* temporary file */
if (mode == PLAY) {
if (!name) {
fd = 0;
name = "stdin";
} else {
if ((fd = open (name, O_RDONLY, 0)) == -1) {
perror(name);
exit(-1);
}
}
read(fd, &head, sizeof(head));
if (!header_check(&head)) exit(-1);
if (!force_stereo) stereo = (head.modus == 2);
length = head.data_length;
if (!force_speed) speed = head.sample_fq;
if (!force_sample_size) sample_size = head.bit_p_spl;
} else { /* mode = RECORD */
remove(tmp_name);
if ((fd = open (tmp_name, O_WRONLY | O_CREAT, 0666)) == -1) {
perror(tmp_name);
exit(-1);
}
/* create header */
strncpy(head.main_chunk, "RIFF", 4);
strncpy(head.chunk_type, "WAVE", 4);
strncpy(head.sub_chunk, "fmt ", 4);
strncpy(head.data_chunk, "data", 4);
head.length = 0; /* to be calculated later */
head.length_chunk = 16;
head.format = 1;
head.modus = stereo ? 2 : 1;
head.sample_fq = speed;
if (!stereo) /* mono */
if (sample_size == 8)
head.byte_p_spl = 1;
else
head.byte_p_spl = 2;
else /* stereo */
if (sample_size == 8)
head.byte_p_spl = 2;
else
head.byte_p_spl = 4;
head.byte_p_sec = speed * head.byte_p_spl;
head.bit_p_spl = sample_size;
head.data_length = 0; /* to be calculated later */
}
if (!time_limit)
count = 0x7fffffff;
else {
count = time_limit * speed;
if (stereo) count *= 2;
if (sample_size != 8) count *=2;
}
if (!quiet_mode) {
if (mode == PLAY)
fprintf(stderr, "Playing: %s", name);
else
if (!name)
fprintf(stderr, "Recording: stdout");
else
fprintf(stderr, "Recording: %s", name);
if (!time_limit)
fprintf(stderr, " (full-song)\n");
else
fprintf(stderr, " %u secs\n", time_limit);
if (stereo)
fprintf(stderr, "Stereo-Sample");
else
fprintf(stderr, "Mono-Sample");
fprintf(stderr, ", speed: %u Hz, %u Bit per Sample\n", speed, sample_size);
}
audio = open(AUDIO, omode, 0);
if (audio == -1) {
perror(AUDIO);
exit(-1);
}
abuf_size = ioctl(audio, SNDCTL_DSP_GETBLKSIZE);
if (abuf_size < 4096 || abuf_size > 65536) {
if (abuf_size == -1)
perror(AUDIO);
else
fprintf(stderr, "Invalid audio buffer size %d\n", abuf_size);
exit(-1);
}
if ((audiobuf = malloc(abuf_size)) == NULL) {
fprintf(stderr, "Unable to allocate output buffer\n");
exit(-1);
}
if (ioctl(audio, SNDCTL_DSP_SAMPLESIZE, sample_size) != sample_size) {
fprintf(stderr, "Unable to set sample size\n");
exit(-1);
}
stereo = ioctl(audio, SNDCTL_DSP_STEREO, stereo);
if ((speed = ioctl(audio, SNDCTL_DSP_SPEED, speed)) == -1) {
fprintf(stderr, "Unable to set audio speed\n");
perror(AUDIO);
exit(-1);
}
if (mode == PLAY) {
while(count) {
c = count;
if (c > abuf_size) c = abuf_size;
if ((l=read(fd, audiobuf, c)) > 0) {
if (write(audio, audiobuf, l) != l) {
perror(AUDIO);
exit(-1);
}
count -= l;
} else {
if (l == -1) {
perror(name);
exit(-1);
}
count = 0; /* stop */
}
}
if (fd) close(fd);
close(audio);
} else { /* mode = RECORD */
if (!quiet_mode) fprintf(stderr, "...recording\n");
while(count) {
c = count;
if (c > abuf_size) c = abuf_size;
if ((l=read(audio, audiobuf, c)) > 0) {
if (write(fd, audiobuf, l) != l) {
perror(tmp_name);
exit(-1);
}
count -= l;
head.data_length += l;
} else {
if (l == -1) {
perror (AUDIO);
exit(-1);
}
}
}
/* now lets correct the header */
close(fd);
close(AUDIO);
head.length = head.data_length + 36;
/* copy the temporary file to the output file with corrected header */
if (!name) {
fd = 1;
name = "stdout";
} else {
remove(name);
if ((fd = open(name, O_WRONLY | O_CREAT, 0666)) == -1) {
perror(name);
exit(-1);
}
}
if ((fd1 = open(tmp_name, O_RDONLY, 0)) == -1) {
perror(tmp_name);
exit(-1);
}
if (write(fd, &head, sizeof(head)) != sizeof(head)) {
perror(name);
exit(-1);
}
if (!quiet_mode) fprintf(stderr, "...copying\n");
while (l = read(fd1, audiobuf, abuf_size)) {
if (write(fd, audiobuf, l) != l) {
perror(name);
exit(-1);
}
}
close(fd);
close(fd1);
remove(tmp_name);
if (!quiet_mode) fprintf(stderr, "READY\n");
}
}
main(int argc, char *argv[])
{
char c;
if (strstr(argv[0], "play")) {
mode = PLAY;
omode = O_WRONLY;
} else if (strstr(argv[0], "record")) {
mode = RECORD;
omode = O_RDONLY;
} else {
fprintf(stderr, "%s: command should either be named play or record\n", argv[0]);
exit(-1);
}
while((c = getopt(argc, argv, "qs:St:b:h")) != EOF)
switch (c) {
case 'q': quiet_mode=1; break;
case 's': speed = atoi(optarg); force_speed = 1; break;
case 'S': stereo = force_stereo = 1; break;
case 't': time_limit = atoi(optarg); break;
case 'b': sample_size = atoi(optarg); force_sample_size = 1; break;
case 'h':
fprintf(stderr,
"Usage: %s [-h] [-q] [-s speed] [-S] [-t limit] [-b bits] filename...\n\n", argv[0]);
fprintf(stderr, "Switches:\n -h .. displays this help text\n");
fprintf(stderr, " -q .. quiet mode; don't display");
fprintf(stderr, " any information about the sample\n");
fprintf(stderr, " -s .. force speed\n -S .. force stereo\n");
fprintf(stderr, " -t .. time limit\n");
fprintf(stderr, " -b .. force bit_p_spl (8, 12, 16)\n\n");
fprintf(stderr, "Normally speed, stereo/mono and bit_p_spl");
fprintf(stderr, " will be read from the given file. Using the\n");
fprintf(stderr, "switches shown above you can set your own.\n");
exit(-1);
default: fprintf(stderr,
"Usage: %s [-h] [-q] [-s speed] [-S] [-t limit] [-b bits] filename...\n\n", argv[0]);
exit(-1);
}
if (mo